#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
统一混淆器
"""

import os
import re
import time
from typing import Dict, List, Any, Optional, Tuple
from pathlib import Path

from core.code_injector_module.code_injector import CodeInjector
from core.code_injector_module.dead_code_injector import DeadCodeInjector
from core.code_injector_module.ast_code_injector import ASTCodeInjector
from core.code_injector_module.ast_dead_code_injector import ASTDeadCodeInjector
from core.code_injector_module.dummy_code_generator import DummyCodeGenerator
from core.code_injector_module.image_obfuscator import ImageObfuscator

from ..interfaces_module.obfuscator import (
    IObfuscationStrategy,
    ObfuscationContext,
    ObfuscationResult,
    ObfuscationLevel
)
from ..interfaces_module.analyzer import AnalysisOptions
from ..interfaces_module.processor import TaskItem
from ..builtin_config_module.builtin_config import BuiltInConfig
from ..utils_module.logger import ObfuscationLogger
from ..utils_module.language_utils import (
    collect_extensions,
    detect_language_for_file,
    SUPPORTED_EXTENSIONS,
    SUPPORTED_LANGUAGES,
)
from .smart_name_generator import SmartNameGenerator, SymbolType


class BaseStrategy(IObfuscationStrategy):
    """基础策略类"""

    def __init__(self, config: BuiltInConfig, logger: ObfuscationLogger):
        self.config = config
        self.logger = logger
        # 初始化智能名称生成器
        self.name_generator = SmartNameGenerator()
        # 初始化替换引擎
        from ..processing_module.replacement_engine import ReplacementEngine
        from .thread_safe_manager import ThreadSafeSymbolManager
        self.symbol_manager = ThreadSafeSymbolManager()
        self.replacement_engine = ReplacementEngine(
            symbol_manager=self.symbol_manager,
            logger=logger,
            use_mmap=True
        )

    def execute(self, context: ObfuscationContext) -> ObfuscationResult:
        """执行混淆"""
        result = ObfuscationResult()
        start_time = time.time()

        try:
            self.logger.log_operation("混淆执行", f"使用{self.get_strategy_name()}策略")

            # 收集源文件
            source_files = self._collect_source_files(context.project_path, context.languages)

            # 尝试使用 LSP 进行重命名（若启用）
            lsp_metadata = self._attempt_lsp_rename(context)

            # 应用符号映射
            for file_path in source_files:
                if self._apply_mapping(file_path, context):
                    result.files_processed += 1

            result.symbols_obfuscated = len(context.symbol_map)
            result.symbol_map = context.symbol_map
            result.success = True
            if lsp_metadata:
                result.metadata['lsp'] = lsp_metadata

        except Exception as e:
            result.success = False
            result.errors.append(str(e))
            self.logger.log_error(f"混淆失败: {e}")

        result.processing_time = time.time() - start_time
        return result

    def generate_symbol_mapping(self, symbols: List[str], context: ObfuscationContext) -> Dict[str, str]:
        """
        生成符号映射（改进版本）

        使用智能名称生成器，根据混淆级别选择策略：
        - BASIC: 词典模式（自然英文单词）
        - STANDARD: 混合模式（70%词典 + 30%随机）
        - ADVANCED: 混合模式（上下文感知）
        - MAXIMUM: 随机模式（完全哈希）
        """
        mapping = {}
        level = context.obfuscation_level

        symbol_languages = context.metadata.get('symbol_languages', {})

        # 根据混淆级别选择命名策略
        if level == ObfuscationLevel.BASIC:
            naming_style = "dictionary"
        elif level == ObfuscationLevel.STANDARD:
            naming_style = "hybrid"
        elif level == ObfuscationLevel.ADVANCED:
            naming_style = "hybrid"
        else:  # MAXIMUM
            naming_style = "random"

        # 重置生成器（确保干净状态）
        self.name_generator.reset()

        # 批量生成映射
        non_reserved_symbols = [
            s for s in symbols
            if not context.is_symbol_reserved(
                s,
                language=symbol_languages.get(s, ""),
                context=context.platform
            )
        ]

        if non_reserved_symbols:
            # 尝试推断符号类型
            symbol_types = {}
            for symbol in non_reserved_symbols:
                symbol_types[symbol] = self.name_generator.detect_symbol_type(symbol)

            # 生成映射
            mapping = self.name_generator.generate_batch(
                non_reserved_symbols,
                symbol_types=symbol_types,
                style=naming_style
            )

            # 添加到上下文
            for original, obfuscated in mapping.items():
                context.add_mapping(original, obfuscated)

            # 记录统计信息
            stats = self.name_generator.get_statistics()
            self.logger.log_operation(
                "符号映射生成",
                f"生成 {stats['total_names']} 个混淆名称，风格: {naming_style}"
            )

        return mapping

    def validate_mapping(self, mapping: Dict[str, str], context: ObfuscationContext) -> bool:
        """验证映射无冲突"""
        if not mapping:
            return True

        obfuscated_names = set()
        for _, obfuscated in mapping.items():
            if obfuscated in obfuscated_names:
                self.logger.log_warning(f"符号映射冲突: {obfuscated}")
                return False
            obfuscated_names.add(obfuscated)
        return True

    def get_strategy_name(self) -> str:
        """获取策略名称"""
        return self.__class__.__name__

    def get_supported_languages(self) -> List[str]:
        """支持的语言"""
        return list(SUPPORTED_LANGUAGES)

    def supports_feature(self, feature: str) -> bool:
        """是否支持特性"""
        return feature in ['basic_obfuscation']

    def _collect_source_files(self, project_path: str, languages: List[str]) -> List[str]:
        """收集源文件"""
        source_files = []
        valid_exts = collect_extensions(languages) if languages else set()

        if not valid_exts:
            valid_exts = set(SUPPORTED_EXTENSIONS)

        for root, dirs, files in os.walk(project_path):
            # 跳过隐藏和构建目录
            dirs[:] = [d for d in dirs if not d.startswith('.')
                      and d not in ['build', 'dist', 'node_modules']]

            for file in files:
                if Path(file).suffix.lower() in valid_exts:
                    source_files.append(os.path.join(root, file))

        return source_files

    def _apply_mapping(self, file_path: str, context: ObfuscationContext) -> bool:
        """
        应用符号映射到文件

        使用 ReplacementEngine 进行更安全、更精确的替换
        """
        mapping = context.symbol_map
        if not mapping:
            return True

        try:
            # 使用 ReplacementEngine 进行替换
            # 它会自动处理注释、字符串、上下文分析等
            result = self.replacement_engine.replace_in_file(
                file_path=file_path,
                replacements=mapping,
                dry_run=self.config.dry_run or context.options.get('dry_run', False)
            )

            # 记录结果
            if result.total_replacements > 0:
                if self.config.dry_run or context.options.get('dry_run'):
                    self.logger.log_file_processing(file_path, f"dry-run (发现 {result.total_replacements} 个替换)")
                else:
                    self.logger.log_file_processing(file_path, f"已混淆 ({result.total_replacements} 个替换)")
            else:
                self.logger.log_file_processing(file_path, "无需混淆")

            # 记录错误
            for error in result.errors:
                self.logger.log_error(f"{file_path}: {error}")

            return len(result.errors) == 0

        except Exception as e:
            self.logger.log_error(f"应用映射失败 {file_path}: {e}")
            return False

    def _attempt_lsp_rename(self, context: ObfuscationContext) -> Optional[Dict[str, Any]]:
        """
        在执行正则替换前尝试通过 LSP 重命名符号。

        Args:
            context: 混淆上下文

        Returns:
            dict: LSP 相关的统计信息，未启用或失败时返回 None
        """
        features = getattr(self.config, 'advanced_features', None)
        if not features or not getattr(features, 'lsp_enabled', False):
            return None

        try:
            from ..lsp_module.lsp_renamer import LSPRenamer
        except Exception as exc:
            self.logger.log_operation("LSP", f"模块不可用: {exc}")
            return {'enabled': True, 'available': False, 'error': str(exc)}

        class _ReplacementFallbackRenamer:
            def __init__(self, strategy: 'BaseStrategy', ctx: ObfuscationContext):
                self.strategy = strategy
                self.context = ctx
                self.dry_run = strategy.config.dry_run or ctx.options.get('dry_run', False)

            def rename(self, file_path, old_name, new_name):
                mapping = {old_name: new_name}
                try:
                    result = self.strategy.replacement_engine.replace_in_file(
                        file_path=str(file_path),
                        replacements=mapping,
                        dry_run=self.dry_run
                    )
                    for error in result.errors:
                        self.strategy.logger.log_error(f"LSP回退失败 {file_path}: {error}")
                    return result.total_replacements > 0 and not result.errors
                except Exception as exc:
                    self.strategy.logger.log_error(f"LSP回退异常 {file_path}: {exc}")
                    return False

        fallback_renamer = _ReplacementFallbackRenamer(self, context)
        lsp_renamer = LSPRenamer(context.project_path, fallback_renamer=fallback_renamer)

        try:
            rename_result = lsp_renamer.rename_symbols(context.symbol_map)
            metadata = {
                'enabled': True,
                'available': True,
                'success': rename_result.success,
                'renamed': rename_result.renamed_symbols,
                'failed': rename_result.failed_symbols,
                'errors': rename_result.errors,
                'warnings': rename_result.warnings,
            }
            if rename_result.success and getattr(rename_result, 'total_symbols', None) is not None:
                metadata['total'] = rename_result.total_symbols
                if rename_result.total_symbols == rename_result.renamed_symbols:
                    context.symbol_map.clear()
                    metadata['symbol_map_cleared'] = True

            if rename_result.success:
                self.logger.log_operation(
                    "LSP",
                    f"LSP 重命名成功 {rename_result.renamed_symbols}/{rename_result.total_symbols}"
                )
            else:
                self.logger.log_operation(
                    "LSP",
                    f"LSP 重命名部分失败: 成功 {rename_result.renamed_symbols}, 失败 {rename_result.failed_symbols}"
                )
                for err in rename_result.errors:
                    self.logger.log_warning(f"LSP 重命名错误: {err}")

            return metadata
        except Exception as exc:
            self.logger.log_operation("LSP", f"LSP 重命名失败: {exc}")
            return {
                'enabled': True,
                'available': True,
                'success': False,
                'error': str(exc),
            }
        finally:
            try:
                lsp_renamer.cleanup()
            except Exception as exc:
                self.logger.log_warning(f"LSP 清理失败: {exc}")


class Obfuscator:
    """统一混淆器主类"""

    def __init__(self, config: BuiltInConfig, logger: ObfuscationLogger):
        """初始化"""
        self.config = config
        self.logger = logger

        # 初始化核心组件
        from ..analysis_module.project_analyzer import ProjectAnalyzer
        from ..extractors_module.symbol_extractor import SymbolExtractor
        from ..processing_module.task_processor import UnifiedTaskProcessor

        self.analyzer = ProjectAnalyzer(config, logger)
        self.symbol_extractor = SymbolExtractor(config, logger)
        self.task_processor = UnifiedTaskProcessor(config, logger)

        # 单一策略实例（所有级别共用）
        self.strategy = BaseStrategy(config, logger)

        # 初始化高级功能模块
        # 根据配置决定使用AST版本还是普通版本
        use_ast = getattr(config.advanced_features, 'use_ast_injection', True) if hasattr(config, 'advanced_features') else True

        if use_ast:
            self.logger.log_operation("注入器选择", "使用AST版本的代码注入器")
            self.code_injector = ASTCodeInjector(config, logger)
            self.dead_code_injector = ASTDeadCodeInjector(config, logger)
        else:
            self.logger.log_operation("注入器选择", "使用传统正则版本的代码注入器")
            self.code_injector = CodeInjector(config, logger)
            self.dead_code_injector = DeadCodeInjector(config, logger)

        self.dummy_code_generator = DummyCodeGenerator(config, logger)
        self.image_obfuscator = ImageObfuscator(config, logger)

        self.logger.log_operation("初始化", "统一混淆器初始化完成")

    def obfuscate(self, project_path: str = None,
                  level: ObfuscationLevel = ObfuscationLevel.ADVANCED,
                  options: Dict[str, Any] = None) -> ObfuscationResult:
        """执行混淆"""
        project_path = project_path or self.config.project_path
        self.logger.log_operation("混淆", f"开始混淆: {project_path}")

        # 1. 分析项目
        analysis_options = AnalysisOptions(
            use_cache=options.get('use_cache', True) if options else True,
            incremental=options.get('incremental', False) if options else False,
            deep_analysis=options.get('deep_analysis', True) if options else True
        )
        analysis_result = self.analyzer.analyze(project_path, analysis_options)

        # 2. 创建混淆上下文
        context = ObfuscationContext(
            project_path=project_path,
            platform=analysis_result.platform.value if analysis_result.platform else 'unknown',
            languages=self._detect_languages(analysis_result.files),
            obfuscation_level=level,
            options=options or {},
            config=self.config
        )

        # 3. 生成符号映射
        all_symbols, symbol_languages = self._extract_symbols(analysis_result)
        context.metadata['symbol_languages'] = symbol_languages
        symbol_mapping = self.strategy.generate_symbol_mapping(all_symbols, context)

        if not self.strategy.validate_mapping(symbol_mapping, context):
            return ObfuscationResult(success=False, errors=["符号映射验证失败"])

        # 4. 执行基础混淆
        result = self.strategy.execute(context)

        # 5. 执行高级混淆功能
        self._execute_advanced_features(project_path, result)

        # 6. 处理任务（如果需要）
        if self.task_processor and hasattr(self.task_processor, 'process'):
            tasks = self._create_tasks(analysis_result.files, symbol_mapping)
            processing_result = self.task_processor.process(tasks)
            # 安全地获取处理数量
            if hasattr(processing_result, 'processed_count'):
                result.files_processed = max(result.files_processed, processing_result.processed_count)
            elif hasattr(processing_result, 'success_count'):
                result.files_processed = max(result.files_processed, processing_result.success_count)

        self.logger.log_operation("完成",
            f"处理{result.files_processed}个文件，混淆{result.symbols_obfuscated}个符号")

        return result

    def extract_symbols(self, use_deep_analysis: bool = True) -> Dict[str, List[str]]:
        """提取符号（API兼容）"""
        options = AnalysisOptions(
            use_cache=True,
            incremental=False,
            deep_analysis=use_deep_analysis
        )

        result = self.analyzer.analyze(self.config.project_path, options)

        category_map = {
            'classes': {'class', 'struct', 'interface', 'enum', 'protocol'},
            'methods': {'method', 'function', 'func', 'selector'},
            'properties': {'property', 'field', 'variable', 'var', 'let'},
        }

        categorized: Dict[str, List[str]] = {key: [] for key in category_map}
        seen: Dict[str, set] = {key: set() for key in category_map}

        symbol_entries = result.symbols or {}
        for symbol_type, symbol_dict in symbol_entries.items():
            if not isinstance(symbol_dict, dict):
                continue

            symbol_type_lower = symbol_type.lower()
            target_keys = [
                category for category, keywords in category_map.items()
                if any(keyword in symbol_type_lower for keyword in keywords)
            ]

            for symbol_name in symbol_dict.keys():
                if not target_keys:
                    # 回退策略：根据符号名关键词归类
                    lowered = symbol_name.lower()
                    if any(keyword in lowered for keyword in ('class', 'struct')):
                        target_keys = ['classes']
                    elif any(keyword in lowered for keyword in ('get', 'set', 'func', 'method')):
                        target_keys = ['methods']
                    elif any(keyword in lowered for keyword in ('prop', 'var', 'field')):
                        target_keys = ['properties']
                    else:
                        # 保持未分类符号，避免误归类
                        continue

                for category in target_keys:
                    if symbol_name not in seen[category]:
                        categorized[category].append(symbol_name)
                        seen[category].add(symbol_name)

        return categorized

    def restore_project(self, backup_map: Dict[str, str] = None) -> bool:
        """还原项目（API兼容）"""
        if not backup_map:
            self.logger.log_warning("没有备份映射")
            return False

        try:
            import shutil
            for original_path, backup_path in backup_map.items():
                if os.path.exists(backup_path):
                    shutil.copy2(backup_path, original_path)
                    self.logger.log_operation("还原", f"文件: {original_path}")
            return True

        except Exception as e:
            self.logger.log_error(f"还原失败: {e}")
            return False

    def _detect_languages(self, files: Dict[str, Any]) -> List[str]:
        """检测项目语言"""
        languages = set()

        for file_path, file_info in files.items():
            path = file_info.path if hasattr(file_info, 'path') else file_path
            language = detect_language_for_file(path)
            if language:
                languages.add(language)

        return list(languages)

    def _extract_symbols(self, analysis_result) -> Tuple[List[str], Dict[str, str]]:
        """从分析结果提取符号及其语言"""
        symbols: List[str] = []
        symbol_languages: Dict[str, str] = {}

        symbol_entries = analysis_result.symbols or {}
        for symbol_dict in symbol_entries.values():
            if not isinstance(symbol_dict, dict):
                continue
            for symbol_name, metadata in symbol_dict.items():
                symbols.append(symbol_name)
                if isinstance(metadata, dict):
                    file_path = metadata.get('file')
                    if file_path:
                        language = self._language_from_path(file_path)
                        if language and symbol_name not in symbol_languages:
                            symbol_languages[symbol_name] = language

        # 去重同时保持原始顺序
        unique_symbols = list(dict.fromkeys(symbols))
        return unique_symbols, symbol_languages

    def _language_from_path(self, file_path: str) -> str:
        """根据文件路径推断语言"""
        return detect_language_for_file(file_path) or ''

    def extract_detailed_symbols(self) -> Dict[str, any]:
        """提取详细符号信息"""
        self.logger.log_operation("详细符号提取", "开始提取详细符号")

        try:
            # 使用分析器提取
            from core.interfaces_module.analyzer import AnalysisOptions
            options = AnalysisOptions(
                use_cache=False,
                incremental=False,
                deep_analysis=True,
                analyze_dependencies=True
            )

            result = self.analyzer.analyze(self.config.project_path, options)

            detailed_symbols = {
                'total_files': len(result.files),
                'total_symbols': result.get_total_symbols(),
                'files': {},
                'platform': result.platform.value if result.platform else 'unknown'
            }

            # 按文件组织符号
            for file_path, file_info in result.files.items():
                file_symbols = []
                if hasattr(file_info, 'symbols'):
                    for symbol in file_info.symbols:
                        file_symbols.append({
                            'name': symbol.name,
                            'type': symbol.symbol_type,
                            'visibility': symbol.visibility,
                            'line': symbol.line_number,
                            'is_system': symbol.is_system
                        })

                detailed_symbols['files'][file_path] = {
                    'language': file_info.language,
                    'symbols': file_symbols,
                    'symbol_count': len(file_symbols)
                }

            self.logger.log_operation("详细符号提取完成", f"提取了 {detailed_symbols['total_symbols']} 个符号")
            return detailed_symbols

        except Exception as e:
            self.logger.log_error(f"详细符号提取失败: {e}")
            return {'error': str(e)}

    def analyze_symbol_usage(self, symbols: Dict[str, List[str]]) -> Dict[str, any]:
        """分析符号使用情况"""
        self.logger.log_operation("符号使用分析", "开始分析符号使用")

        try:
            usage_stats = {
                'total_symbols': 0,
                'by_type': {},
                'by_visibility': {},
                'top_used': []
            }

            # 统计符号类型
            for symbol_type, symbol_list in symbols.items():
                usage_stats['by_type'][symbol_type] = len(symbol_list)
                usage_stats['total_symbols'] += len(symbol_list)

            self.logger.log_operation("符号使用分析完成", f"分析了 {usage_stats['total_symbols']} 个符号")
            return usage_stats

        except Exception as e:
            self.logger.log_error(f"符号使用分析失败: {e}")
            return {'error': str(e)}

    def extract_system_symbols(self) -> Dict[str, List[str]]:
        """提取系统符号"""
        self.logger.log_operation("系统符号提取", "开始提取系统符号")

        try:
            system_symbols = {
                'swift': [],
                'objc': [],
                'java': [],
                'kotlin': []
            }

            # 使用分析器提取
            from core.interfaces_module.analyzer import AnalysisOptions
            options = AnalysisOptions(
                use_cache=False,
                incremental=False,
                deep_analysis=True
            )

            result = self.analyzer.analyze(self.config.project_path, options)

            # 提取系统符号
            # 注意：FileInfo没有symbols属性，符号存储在result.symbols中
            # 这里需要从result.symbols中提取系统符号
            for symbol_type, symbol_dict in result.symbols.items():
                if isinstance(symbol_dict, dict):
                    for symbol_name, symbol_info in symbol_dict.items():
                        # 检查是否是系统符号（通常以特定前缀开头或在系统框架中）
                        if self._is_system_symbol(symbol_name, symbol_info):
                            # 根据文件路径确定语言
                            if isinstance(symbol_info, dict) and 'file' in symbol_info:
                                file_path = symbol_info['file']
                                if file_path in result.files:
                                    lang = result.files[file_path].language
                                    if lang in system_symbols:
                                        system_symbols[lang].append(symbol_name)

            # 去重
            for lang in system_symbols:
                system_symbols[lang] = list(set(system_symbols[lang]))

            total = sum(len(v) for v in system_symbols.values())
            self.logger.log_operation("系统符号提取完成", f"提取了 {total} 个系统符号")
            return system_symbols

        except Exception as e:
            self.logger.log_error(f"系统符号提取失败: {e}")
            return {'error': str(e)}

    def _is_system_symbol(self, symbol_name: str, symbol_info: any = None) -> bool:
        """
        判断是否是系统符号
        使用 builtin_config.py 中定义的完整系统符号列表

        Args:
            symbol_name: 符号名称
            symbol_info: 符号信息（预留用于未来扩展）

        Returns:
            是否是系统符号
        """
        from ..builtin_config_module.builtin_config_define import BuiltinConfigDefine

        # 1. 检查是否在保留符号集合中（关键字、系统类型、系统方法）
        reserved_symbols = BuiltinConfigDefine.get_all_reserved_symbols()
        if symbol_name in reserved_symbols:
            return True

        # 2. 检查是否以系统前缀开头
        platform = self.config.platform
        if platform == 'ios' or platform == 'unified':
            if BuiltinConfigDefine.is_system_prefix(symbol_name, 'ios'):
                return True
        if platform == 'android' or platform == 'unified':
            if BuiltinConfigDefine.is_system_prefix(symbol_name, 'android'):
                return True

        # 3. 检查是否匹配生命周期模式
        if platform == 'ios' or platform == 'unified':
            if BuiltinConfigDefine.matches_lifecycle_pattern(symbol_name, 'ios'):
                return True
        if platform == 'android' or platform == 'unified':
            if BuiltinConfigDefine.matches_lifecycle_pattern(symbol_name, 'android'):
                return True

        return False

    def generate_symbol_report(self, symbols: Dict[str, any], output_path: str) -> bool:
        """生成符号报告"""
        try:
            import json
            os.makedirs(os.path.dirname(output_path), exist_ok=True)
            with open(output_path, 'w', encoding='utf-8') as f:
                json.dump(symbols, f, indent=2, ensure_ascii=False)
            self.logger.log_operation("报告生成", f"已保存到 {output_path}")
            return True
        except Exception as e:
            self.logger.log_error(f"报告生成失败: {e}")
            return False

    def _execute_advanced_features(self, project_path: str, result: ObfuscationResult = None):
        """
        执行高级混淆功能

        根据配置执行死代码注入、垃圾代码生成、代码注入和图片混淆

        Args:
            project_path: 项目路径
            result: 混淆结果对象（可选，用于更新统计信息）
        """
        features = self.config.advanced_features

        # 1. 死代码注入
        if features.dead_code_enabled:
            self.logger.log_operation("高级功能", "执行死代码注入")
            self.dead_code_injector.inject_to_project(
                project_path,
                complexity=features.dead_code_complexity,
                probability=features.dead_code_injection_probability
            )

        # 2. 垃圾代码生成
        if features.dummy_code_enabled:
            self.logger.log_operation("高级功能", "生成垃圾代码")
            self.dummy_code_generator.generate_for_project(
                project_path,
                count=features.dummy_code_count,
                complexity=features.dummy_code_complexity
            )

        # 3. 代码注入
        if features.injection_enabled:
            self.logger.log_operation("高级功能", "执行代码注入")
            self.code_injector.inject_from_file(
                features.injection_content_file,
                features.injection_target_dirs
            )

        # 4. 图片混淆
        if features.image_obfuscation_enabled:
            self.logger.log_operation("高级功能", "修改图片MD5")
            self.image_obfuscator.modify_project_images(project_path)

    def inject_code(self, snippets: List[str] = None, use_ast: bool = None) -> bool:
        """
        注入代码片段（公共API）

        Args:
            snippets: 代码片段列表
            use_ast: 是否使用AST分析注入点（None时自动判断）

        Returns:
            是否成功
        """
        try:
            # 判断是否是AST注入器
            is_ast_injector = isinstance(self.code_injector, ASTCodeInjector)

            if snippets:
                # 使用提供的片段
                target_files = self.code_injector._find_target_files(
                    self.config.advanced_features.injection_target_dirs
                )

                if is_ast_injector:
                    # AST注入器使用inject_from_file方法，支持AST分析
                    # 先创建临时文件保存snippets
                    import tempfile
                    with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as f:
                        f.write('\n---\n'.join(snippets))
                        temp_file = f.name

                    result = self.code_injector.inject_from_file(
                        temp_file,
                        self.config.advanced_features.injection_target_dirs,
                        use_ast=use_ast if use_ast is not None else True
                    )

                    # 删除临时文件
                    import os
                    os.unlink(temp_file)
                    return result
                else:
                    # 传统注入器
                    return self.code_injector.inject_snippets(snippets, target_files)
            else:
                # 从配置文件读取
                if is_ast_injector:
                    return self.code_injector.inject_from_file(
                        self.config.advanced_features.injection_content_file,
                        self.config.advanced_features.injection_target_dirs,
                        use_ast=use_ast if use_ast is not None else True
                    )
                else:
                    return self.code_injector.inject_from_file(
                        self.config.advanced_features.injection_content_file,
                        self.config.advanced_features.injection_target_dirs
                    )
        except Exception as e:
            self.logger.log_error(f"代码注入失败: {e}")
            return False

    def modify_image_md5(self) -> bool:
        """
        修改图片MD5（公共API）

        Returns:
            是否成功
        """
        try:
            return self.image_obfuscator.modify_project_images(self.config.project_path)
        except Exception as e:
            self.logger.log_error(f"图片MD5修改失败: {e}")
            return False

    def restore_images(self) -> bool:
        """
        恢复图片（公共API）

        Returns:
            是否成功
        """
        try:
            return self.image_obfuscator.restore_images(self.config.project_path)
        except Exception as e:
            self.logger.log_error(f"图片恢复失败: {e}")
            return False

    def clean_image_backups(self) -> bool:
        """
        清理图片备份（公共API）

        Returns:
            是否成功
        """
        try:
            return self.image_obfuscator.clean_backups(self.config.project_path)
        except Exception as e:
            self.logger.log_error(f"清理失败: {e}")
            return False

    def generate_advanced_dummy_code(self) -> bool:
        """
        生成高级Dummy代码（公共API）

        Returns:
            是否成功
        """
        try:
            return self.dummy_code_generator.generate_for_project(
                self.config.project_path,
                count=self.config.advanced_features.dummy_code_count,
                complexity=self.config.advanced_features.dummy_code_complexity
            )
        except Exception as e:
            self.logger.log_error(f"Dummy代码生成失败: {e}")
            return False

    def inject_dead_code(self, complexity: str = None, probability: float = None, use_ast: bool = None) -> bool:
        """
        注入死代码（公共API）

        Args:
            complexity: 复杂度级别 (low/medium/high/extreme)，None时使用配置
            probability: 注入概率 (0.0-1.0)，None时使用配置
            use_ast: 是否使用AST分析（None时自动判断）

        Returns:
            是否成功
        """
        try:
            # 判断是否是AST死代码注入器
            is_ast_injector = isinstance(self.dead_code_injector, ASTDeadCodeInjector)

            if is_ast_injector:
                # 使用AST版本
                return self.dead_code_injector.inject_to_project(
                    self.config.project_path,
                    complexity=complexity,
                    probability=probability,
                    use_ast=use_ast if use_ast is not None else True
                )
            else:
                # 使用传统版本
                return self.dead_code_injector.inject_to_project(
                    self.config.project_path,
                    complexity=complexity,
                    probability=probability
                )
        except Exception as e:
            self.logger.log_error(f"死代码注入失败: {e}")
            return False

    def _create_tasks(self, files, mapping) -> List[TaskItem]:
        """创建处理任务"""
        tasks = []
        for file_info in files:
            file_path = file_info.path if hasattr(file_info, 'path') else file_info
            tasks.append(TaskItem(
                task_id=file_path,
                task_type='obfuscate',
                data={'file_path': file_path, 'mapping': mapping}
            ))
        return tasks
